package com.gcloud.mesh.alert.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.jeecg.common.exception.ParamException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.gcloud.framework.db.PageResult;
import com.gcloud.mesh.alert.dao.LinkmanDao;
import com.gcloud.mesh.alert.dao.PolicyDao;
import com.gcloud.mesh.alert.dao.PolicyLinkmanDao;
import com.gcloud.mesh.alert.dao.RuleDao;
import com.gcloud.mesh.alert.entity.LinkmanEntity;
import com.gcloud.mesh.alert.entity.PolicyEntity;
import com.gcloud.mesh.alert.entity.PolicyLinkmanEntity;
import com.gcloud.mesh.alert.entity.RuleEntity;
import com.gcloud.mesh.asset.entity.IaasEntity;
import com.gcloud.mesh.header.exception.BaseException;
import com.gcloud.mesh.header.msg.alert.AddPolicyLinkmanMsg;
import com.gcloud.mesh.header.msg.alert.CreatePolicyMsg;
import com.gcloud.mesh.header.msg.alert.DeletePolicyLinkmanMsg;
import com.gcloud.mesh.header.msg.alert.DeletePolicyMsg;
import com.gcloud.mesh.header.msg.alert.DetailPolicyMsg;
import com.gcloud.mesh.header.msg.alert.PagePolicyMsg;
import com.gcloud.mesh.header.msg.alert.UpdatePolicyMsg;
import com.gcloud.mesh.header.vo.alert.LinkmanVo;
import com.gcloud.mesh.header.vo.alert.PolicyVo;
import com.gcloud.mesh.header.vo.alert.RuleVo;

@Service
public class PolicyService {
	@Autowired
	PolicyDao policyDao;

	@Autowired
	PolicyLinkmanDao policyLinkmanDao;

	@Autowired
	RuleDao ruleDao;

	@Autowired
	LinkmanDao linkmanDao;

	public List<PolicyVo> list() {
		List<PolicyVo> policyVos = new ArrayList<PolicyVo>();

		for (PolicyEntity entity : policyDao.findAll()) {
			PolicyVo vo = new PolicyVo();

			vo.setChannelSilence(entity.getChannelSilence());
			vo.setCreateTime(entity.getCreateTime());
			vo.setEnable(entity.getEnable());
			vo.setEnableEndTime(entity.getEnableEndTime());
			vo.setEnableStartTime(entity.getEnableStartTime());
			vo.setId(entity.getId());
			vo.setNotifyEnable(entity.getNotifyEnable());
			vo.setPolicyName(entity.getPolicyName());
			vo.setPlatform(entity.getPlatformType());
			vo.setRegionId(entity.getRegionId());

			policyVos.add(vo);
		}

		return policyVos;
	}

	public String create(CreatePolicyMsg msg) {
		List<PolicyEntity> result = policyDao.findByProperty("policyName", msg.getPolicyName());
		if (result.size() > 0) {
			throw new ParamException("PolicyNameIsExist", "策略名称已经存在");
		}

		PolicyEntity entity = new PolicyEntity();
		entity.setChannelSilence(msg.getChannelSilence());
		entity.setEnable(msg.getEnable());
		entity.setEnableEndTime(msg.getEnableEndTime());
		entity.setEnableStartTime(msg.getEnableStartTime());
		entity.setId(UUID.randomUUID().toString());
		entity.setNotifyEnable(msg.getNotifyEnable());
		entity.setPolicyName(msg.getPolicyName());
		entity.setCreateTime(new Date());

		entity.setPlatformType(msg.getPlatformType());
		entity.setRegionId(msg.getRegionId());

		for (RuleVo ruleVo : msg.getRuleVos()) {

			Map<String, Object> props = new HashMap<String, Object>();
			props.put("policy_id", entity.getId());
			props.put("meter", ruleVo.getMeter());

			RuleEntity rule = ruleDao.findUniqueByProperties(props);
			if (rule != null) {
				throw new ParamException("::监控项已存在");
			}
			if (ruleVo.getThreshold() > 999999 || ruleVo.getThreshold() < 0) {
				throw new ParamException("::阈值取值范围0~999999");
			}
			if (ruleVo.getMeter().contains("cpu_util") || ruleVo.getMeter().contains("memroy_util")) {
				if (ruleVo.getThreshold() > 100 || ruleVo.getThreshold() < 0) {
					throw new ParamException("::阈值取值范围0~100");
				}
			}

			RuleEntity ruleEntity = new RuleEntity();
			ruleEntity.setPolicyId(entity.getId());
			ruleEntity.setCreateTime(new Date());
			ruleEntity.setDuration(ruleVo.getDuration());
			ruleEntity.setEnabled(ruleVo.getEnabled());
			ruleEntity.setId(UUID.randomUUID().toString());
			ruleEntity.setLevel(ruleVo.getLevel());

			ruleEntity.setMeter(ruleVo.getMeter());
			ruleEntity.setResourceType(ruleVo.getResourceType());
			ruleEntity.setResourceId(ruleVo.getResourceId());

			ruleEntity.setThreshold(ruleVo.getThreshold());
			ruleEntity.setStatistics(ruleVo.getStatistics());
			ruleEntity.setComparisonOperator(ruleVo.getComparisonOperator());
			ruleDao.save(ruleEntity);
		}

		policyDao.save(entity);

		return entity.getId();
	}

	public void delete(DeletePolicyMsg msg) {
		List<PolicyLinkmanEntity> policyLinkmanEntitys = policyLinkmanDao.findByProperty("policyId", msg.getPolicyId());
		for (PolicyLinkmanEntity policyLinkmanEntity : policyLinkmanEntitys) {
			policyLinkmanDao.deleteById(policyLinkmanEntity.getId().toString());
		}

		List<RuleEntity> ruleEntitys = ruleDao.findByProperty("policyId", msg.getPolicyId());
		for (RuleEntity ruleEntity : ruleEntitys) {
			ruleDao.deleteById(ruleEntity.getId());
		}

		policyDao.deleteById(msg.getPolicyId());
	}

	public PageResult<PolicyVo> page(PagePolicyMsg request) {
		return policyDao.page(request.getPageNo(), request.getPageSize(), request.getResourceType(), PolicyVo.class);
	}

	public PolicyVo detail(DetailPolicyMsg msg) {
		List<RuleEntity> ruleEntitys = ruleDao.findByProperty("policyId", msg.getPolicyId());

		List<RuleVo> ruleVos = new ArrayList<RuleVo>();
		for (RuleEntity ruleEntity : ruleEntitys) {
			RuleVo ruleVo = new RuleVo();
			ruleVo.setComparisonOperator(ruleEntity.getComparisonOperator());
			ruleVo.setCreateTime(ruleEntity.getCreateTime());
			ruleVo.setDuration(ruleEntity.getDuration());
			ruleVo.setEnabled(ruleEntity.isEnabled());
			ruleVo.setId(ruleEntity.getId());
			ruleVo.setLevel(ruleEntity.getLevel());
			ruleVo.setMeter(ruleEntity.getMeter());
			ruleVo.setPolicyId(ruleEntity.getPolicyId());
			ruleVo.setResourceId(ruleEntity.getResourceId());
			ruleVo.setResourceType(ruleEntity.getResourceType());
			ruleVo.setStatistics(ruleEntity.getStatistics());
			ruleVo.setThreshold(ruleEntity.getThreshold());
			ruleVo.setUnit(ruleEntity.getUnit());
			ruleVo.setMeterChnName(ruleEntity.getMeterChnName());

			ruleVos.add(ruleVo);
		}

		List<PolicyLinkmanEntity> policyLinkmanEntitys = policyLinkmanDao.findByProperty("policyId", msg.getPolicyId());
		List<LinkmanVo> linkmanVos = new ArrayList<LinkmanVo>();
		for (PolicyLinkmanEntity policyLinkmanEntity : policyLinkmanEntitys) {
			LinkmanEntity linkmanEntity = linkmanDao.getById(policyLinkmanEntity.getLinkmanId());
			if (linkmanEntity != null) {
				LinkmanVo linkmanVo = new LinkmanVo();
				linkmanVo.setCreateTime(linkmanEntity.getCreateTime());
				linkmanVo.setEmail(linkmanEntity.getEmail());
				linkmanVo.setId(linkmanEntity.getId());
				linkmanVo.setPhoneNumber(linkmanEntity.getPhoneNumber());
				linkmanVo.setUserName(linkmanEntity.getUserName());
				linkmanVos.add(linkmanVo);
			}
		}

		PolicyVo policyVo = new PolicyVo();
		policyVo.setRuleVos(ruleVos);
		policyVo.setLinkmanVos(linkmanVos);

		PolicyEntity policyEntity = policyDao.getById(msg.getPolicyId());
		policyVo.setChannelSilence(policyEntity.getChannelSilence());
		policyVo.setEnable(policyEntity.getEnable());
		policyVo.setEnableStartTime(policyEntity.getEnableStartTime());
		policyVo.setEnableEndTime(policyEntity.getEnableEndTime());
		policyVo.setNotifyEnable(policyEntity.getNotifyEnable());
		policyVo.setId(policyEntity.getId());
		policyVo.setPolicyName(policyEntity.getPolicyName());

		policyVo.setPlatform(policyEntity.getPlatformType());
		policyVo.setRegionId(policyEntity.getRegionId());
		return policyVo;
	}

	public void update(UpdatePolicyMsg msg) {
		PolicyEntity policyEntity = policyDao.getById(msg.getPolicyId());
		if (policyEntity == null) {
			throw new ParamException("update_policy_id_not_found", "没有找到对应的策略");
		}

		if (msg.getChannelSilence() != null) {
			policyEntity.setChannelSilence(msg.getChannelSilence());
		}

		if (msg.getEnableEndTime() != null) {
			policyEntity.setEnableEndTime(msg.getEnableEndTime());
		}

		if (msg.getEnableStartTime() != null) {
			policyEntity.setEnableStartTime(msg.getEnableStartTime());
		}

		if (msg.getNotifyEnable() != null) {
			policyEntity.setNotifyEnable(msg.getNotifyEnable());
		}

		if (msg.getPolicyName() != null) {
			policyEntity.setPolicyName(msg.getPolicyName());
			List<PolicyEntity> result = policyDao.findByProperty("policyName", msg.getPolicyName());
			if (result.size() > 0) {
				for (PolicyEntity entity : result) {
					if (!entity.getId().equals(msg.getPolicyId())) {
						throw new ParamException("PolicyNameIsExist", "策略名称已经存在");
					}
				}
			}
		}

		if (msg.getEnable() != null) {
			policyEntity.setEnable(msg.getEnable());
		}

		policyDao.update(policyEntity);

		if (msg.getRuleVos() != null) {
			for (RuleVo ruleVo : msg.getRuleVos()) {
				RuleEntity ruleEntity = ruleDao.getById(ruleVo.getId());

				if (ruleEntity == null) {

					Map<String, Object> props = new HashMap<String, Object>();
					props.put("policy_id", policyEntity.getId());
					props.put("meter", ruleVo.getMeter());

					RuleEntity rule = ruleDao.findUniqueByProperties(props);
					if (rule != null) {
						throw new ParamException("::监控项已存在");
					}

					if (ruleVo.getThreshold() > 999999 || ruleVo.getThreshold() < 0) {
						throw new ParamException("::阈值取值范围0~999999");
					}
					if (ruleVo.getMeter().contains("cpu_util") || ruleVo.getMeter().contains("memroy_util")) {
						if (ruleVo.getThreshold() > 100 || ruleVo.getThreshold() < 0) {
							throw new ParamException("::阈值取值范围0~100");
						}
					}

					ruleEntity = new RuleEntity();
					ruleEntity.setPolicyId(policyEntity.getId());
					ruleEntity.setId(UUID.randomUUID().toString());
					ruleEntity.setCreateTime(new Date());
					ruleEntity.setDuration(ruleVo.getDuration());
					ruleEntity.setEnabled(ruleVo.getEnabled());
					ruleEntity.setLevel(ruleVo.getLevel());

					ruleEntity.setMeter(ruleVo.getMeter());
					ruleEntity.setResourceType(ruleVo.getResourceType());

					ruleEntity.setThreshold(ruleVo.getThreshold());
					ruleEntity.setStatistics(ruleVo.getStatistics());
					ruleEntity.setComparisonOperator(ruleVo.getComparisonOperator());
					ruleDao.save(ruleEntity);
				} else {

					Map<String, Object> props = new HashMap<String, Object>();
					props.put("policy_id", policyEntity.getId());
					props.put("meter", ruleVo.getMeter());

					RuleEntity rule = ruleDao.findUniqueByProperties(props);
					if (rule != null && !rule.getId().equals(ruleVo.getId())) {
						throw new ParamException("::监控项已存在");
					}

					if (ruleVo.getThreshold() > 999999 || ruleVo.getThreshold() < 0) {
						throw new ParamException("::阈值取值范围0~999999");
					}
					if (ruleVo.getMeter().contains("cpu_util") || ruleVo.getMeter().contains("memroy_util")) {
						if (ruleVo.getThreshold() > 100 || ruleVo.getThreshold() < 0) {
							throw new ParamException("::阈值取值范围0~100");
						}
					}

					ruleEntity.setDuration(ruleVo.getDuration());
					ruleEntity.setEnabled(ruleVo.getEnabled());
					ruleEntity.setLevel(ruleVo.getLevel());

					ruleEntity.setMeter(ruleVo.getMeter());
					ruleEntity.setResourceType(ruleVo.getResourceType());

					ruleEntity.setThreshold(ruleVo.getThreshold());
					ruleEntity.setStatistics(ruleVo.getStatistics());
					ruleEntity.setComparisonOperator(ruleVo.getComparisonOperator());
					ruleDao.update(ruleEntity);
				}

			}
		}
	}

	public void addPolicyLinkman(AddPolicyLinkmanMsg msg) {
		Map<String, Object> where = new HashMap<String, Object>();
		for (String linkmanId : msg.getLinkmanIds()) {
			where.put("policyId", msg.getPolicyId());
			where.put("linkmanId", linkmanId);
			List<PolicyLinkmanEntity> policyLinkmanEntitys = policyLinkmanDao.findByProperties(where);
			if (policyLinkmanEntitys.size() > 0) {
				continue;
			}

			PolicyLinkmanEntity policyLinkmanEntity = new PolicyLinkmanEntity();
			policyLinkmanEntity.setCreateTime(new Date());
			policyLinkmanEntity.setLinkmanId(linkmanId);
			policyLinkmanEntity.setPolicyId(msg.getPolicyId());
			policyLinkmanDao.save(policyLinkmanEntity);
		}
	}

	public void deletePolicyLinkman(DeletePolicyLinkmanMsg msg) {
		Map<String, Object> where = new HashMap<String, Object>();
		where.put("policyId", msg.getPolicyId());
		where.put("linkmanId", msg.getLinkmanId());
		List<PolicyLinkmanEntity> policyLinkmanEntitys = policyLinkmanDao.findByProperties(where);

		for (PolicyLinkmanEntity policyLinkmanEntity : policyLinkmanEntitys) {
			policyLinkmanDao.deleteById(policyLinkmanEntity.getId().toString());
		}

		// 判断移除联系人之后，策略中还有没有联系人，如果没有了，则更新是否通知
		Map<String, Object> queryPolicy = new HashMap<String, Object>();
		queryPolicy.put("policyId", msg.getPolicyId());
		List<PolicyLinkmanEntity> policyLinkmanLists = policyLinkmanDao.findByProperties(queryPolicy);
		if (policyLinkmanLists == null || policyLinkmanLists.size() == 0) {
			try {
				PolicyEntity entity = policyDao.findUniqueByProperty("id", msg.getPolicyId());
				entity.setNotifyEnable(false);
				policyDao.update(entity);
			} catch (Exception e) {
				throw new BaseException("update_policy_notify", "更新策略通知状态异常！");
			}
		}
	}
}
